Photo by Sébastien Goldberg on Unsplash
Mount Cook, New Zealand
生活情境:當你身處在外商工作,周遭同事都是英文溝通,新來同事,在茶水間相遇,意外發現新同事會講台語,從此你跟新同事在茶水間透過台語加密講八卦,這就是加密解密☕️
打 API 時,怕有心人士竊取資料,可以替你 API 加密、加鹽(Salt)、initialization vector。
資安防護人人有責 💪🏻
https://github.com/krzyzanowskim/CryptoSwift
Swift Package Manager
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMajor(from: "1.8.0"))
import CryptoSwift
反正我從這 stackoverflow 改成我要的需求
Transform Java AES Decryption Code to CryptoSwift
extension String {
// 加密方法
func encrypt(key: String, value: String) -> String {
// 初始化一個空的結果字符串
var result = ""
do {
// 將 key 和 value 轉換為字節數組
let key: [UInt8] = Array(key.utf8)
let value: [UInt8] = Array(value.utf8)
// 創建 AES 加密器,使用 CBC 模式和 pkcs7 填充
let aes = try! AES(key: key, blockMode: CBC(iv: value), padding: .pkcs7)
// 加密當前字符串
let encrypted = try aes.encrypt(Array(self.utf8))
// 將加密後的字節數組轉換為 Base64 格式的字符串
result = encrypted.toBase64() ?? ""
} catch {
// 如果有錯誤,則打印錯誤
print("Error: \(error)")
}
return result
}
// 解密方法
func decrypt(key: String, value: String) -> String {
// 初始化一個空的結果字符串
var result = ""
do {
// 從當前字符串獲取加密的內容
let encrypted = self
// 將 key 和 value 轉換為字節數組
let key: [UInt8] = Array(key.utf8)
let value: [UInt8] = Array(value.utf8)
// 創建 AES 解密器,使用 CBC 模式和 pkcs7 填充
let aes = try! AES(key: key, blockMode: CBC(iv: value), padding: .pkcs7)
// 解密加密的內容
let decrypted = try aes.decrypt(Array(base64: encrypted))
// 將解密後的字節數組轉換為字符串
result = String(data: Data(decrypted), encoding: .utf8) ?? ""
} catch {
// 如果有錯誤,則打印錯誤
print("Error: \(error)")
}
return result
}
}
使用派生鍵 (derived key) 是對密鑰的一種強化方法,通常使用密碼基於鍵的 key derivation function (KDF)。PBKDF2 (Password-Based Key Derivation Function 2) 是其中一個常用的 KDF。
以下是如何使用 Swift 來生成一個派生鍵的例子,這裡使用了 CommonCrypto
庫來實現 PBKDF2:
CommonCrypto
這個模塊。import CommonCrypto
func derivedKey(password: String, salt: Data, iterations: Int, keyLength: Int) -> Data? {
var derivedKeyData = Data(count: keyLength)
let derivationStatus = derivedKeyData.withUnsafeMutableBytes { derivedKeyBytes in
salt.withUnsafeBytes { saltBytes in
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password,
password.count,
saltBytes.baseAddress,
salt.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256),
UInt32(iterations),
derivedKeyBytes.baseAddress,
keyLength
)
}
}
return derivationStatus == kCCSuccess ? derivedKeyData : nil
}
let password = "yourPasswordHere"
let salt = "someRandomSalt".data(using: .utf8)!
let iterations = 10000 // 推薦至少使用 10,000 次迭代
let desiredKeyLength = 32 // 例如,對於 256 位的 AES 鍵
if let derivedKey = derivedKey(password: password, salt: salt, iterations: iterations, keyLength: desiredKeyLength) {
print("Derived Key: \\(derivedKey.base64EncodedString())")
}
請注意,為了提高安全性,應該使用隨機生成的鹽,而不是硬編碼的鹽。而且,迭代次數也應該根據需要進行調整,但總體上,使用更多的迭代次數會增加密鑰派生的計算難度,從而增加安全性。
Tips: 跟後端確認 iterations 是多少,有些語言 iterations 沒設定是 default 某值,解密老半天,才發現前端跟後端 iterations 參數不一樣
Tips: 解密由於會花時間,會有時間差記得要 DispatchGroup 管理多個異步操作。
什么是加密? - 密码、摘要、盐和 IV 指南 | HackerNoon